home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
dskut
/
aspisrc.zip
/
ASPI.C
next >
Wrap
C/C++ Source or Header
|
1992-01-26
|
31KB
|
1,219 lines
#ident "$Id: aspi.c,v 1.1 1992/01/15 01:14:12 chris Exp $"
#include <stdio.h>
#include <fcntl.h>
#include <dos.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#include <errno.h>
/*
* $Log: aspi.c,v $
* Revision 1.1 1992/01/15 01:14:12 chris
* Initial revision
*
*
*
* chris@alderan.sdata.de
*/
#define DWORD unsigned long
#ifndef TAPE_ID
#define TAPE_ID "0:4:0"
#endif
#include "aspi.h"
#include "scsi.h"
#include "scsierr.h"
#ifndef CTCTRL
#include "tar.h"
#endif
static char *aspi_c_id = "$Id: aspi.c,v 1.1 1992/01/15 01:14:12 chris Exp $";
void aspiinit();
extern int errno;
/*
* The complete scsi address of our tape device
*/
int adapter_id, scsi_tape_id, lun_id;
/*
* Because all the scsi functions start with:
* SCSIfunc(adapter_id, scsi_tape_id, lun, .......)
* .. we define a macro "TARGET", so that we can write SCSIfunc(TARGET, ...);
*/
#define TARGET adapter_id, scsi_tape_id, lun_id
#ifndef CTCTRL
/* Flags to for use with the streamer (detected at aspiopen()) */
static int aspifile, no_rewind;
/* This holds the max., and min. recordsize, the streamer can deal with */
static blocklimit lim;
static long recsize; /* the record size to use */
static int logrec; /* log2(recordsize) */
static long apos; /* this holds the current archive file pointer */
static int write_file_mark_on_close;
static int end_of_medium;
static unsigned char rsense[14]; /* array for scsi-sense-data */
/*
* The next two functions are called when you open a file.
* They check if the filename specifies the scsi-tape.
* The filenames used for that are "/dev/ct" - "rewind cartridge tape"
* and "/dev/nrct" - "no rewind cartridge tape" (no rewind on close)
* I just choose those names "/dev/ct" and "/dev/nrct" because the
* filenames are unusual to exist on a MSDOS filesystem and also because
* I'm used to them from my ix386. Anyway, there are no other dependencies
* on those names in the whole program. So, if you prefer to change the
* names to "/dev/rmt0" or whatever, just change them !
* As you can see in aspicreate() and aspiopen(), I still open a
* MSDOS-output-dummy-file. "nul:" is kind of /dev/null for MSDOS
* and I had to do this because the MSDOS code from tar still
* does some operations on this file like setmode(stream) etc. and
* I was too lazy to change the code in tar. So, with this they
* may do setmode()'s on the null-device as long as they want :-)
*/
/*
* Create an archive file
*/
aspicreat(path, mode)
char *path;
int mode;
{
end_of_medium = 0;
if ( !strcmp(path, "/dev/ct") ) {
apos = 0l;
no_rewind = 0;
aspiinit();
write_file_mark_on_close = 1;
return (aspifile=creat("NUL", mode));
} else if ( !strcmp(path,"/dev/nrct") ) {
apos = 0l;
no_rewind = 1;
aspiinit();
write_file_mark_on_close = 1;
return (aspifile=creat("NUL", mode));
}
aspifile = -1;
return creat(path, mode);
}
/*
* Open an archive file
*/
aspiopen(path, oflag, mode)
char *path;
int oflag;
int mode;
{
end_of_medium = 0;
if ( !strcmp(path, "/dev/ct") ) {
apos = 0l;
no_rewind = 0;
aspiinit();
if ( (oflag & O_WRONLY) || (oflag & O_RDWR) )
write_file_mark_on_close = 1;
else write_file_mark_on_close = 0;
return (aspifile=open("NUL", oflag, mode));
} else if ( !strcmp(path,"/dev/nrct") ) {
apos = 0l;
no_rewind = 1;
aspiinit();
if ( (oflag & O_WRONLY) || (oflag & O_RDWR) )
write_file_mark_on_close = 1;
else write_file_mark_on_close = 0;
return (aspifile=open("NUL", oflag, mode));
}
aspifile = -1;
return open(path, oflag, mode);
}
/*
* So, all the other functions now just check if (fileds == aspifile)
* and do redirect the opereation to the tape. Otherwise they just
* hand the request to the original function (e.g aspiread()->read() etc.).
*/
/*
* Read data from an archive file
*/
aspiread(fileds, buf, nbyte)
int fileds;
char *buf;
int nbyte;
{
int i;
unsigned int *u;
if ( fileds == aspifile ) {
u = ( unsigned int * ) &nbyte; /* Hack, I know */
if ( nbyte % ( int ) recsize ) {
( void ) fprintf(stderr,
"aspiread: Illegal blocklen for tape: %u\n", nbyte);
( void ) aspiclose(fileds);
exit(EX_SYSTEM);
}
i = SCSIRead(TARGET, buf, ( long ) *u, logrec, 0, 1, rsense);
if ( i ) { /* If any error ... */
unsigned bytes_read;
if ( i == E$BlankCheck ) { /* EEOM (early end of medium) */
errno = ENOSPC;
if ( (rsense[2] & 0x40) && (rsense[0] &0x80) ) {
/* compute the number of bytes read */
bytes_read = *u - ((rsense[6]+(rsense[5]<<8))<<logrec);
apos += ( long ) bytes_read;
return ( int ) bytes_read;
} else return 0;
} else if ( (i==E$Medium) && (rsense[2] & 0x40) && (rsense[0] & 0x80) ) {
errno = ENOSPC;
bytes_read = *u - ((rsense[6]+(rsense[5]<<8))<<logrec);
apos += ( long ) bytes_read;
return ( int ) bytes_read;
} else {
( void ) fprintf(stderr,"aspiread: errno: %d\n", i);
( void ) aspiclose(fileds);
exit(EX_SYSTEM);
}
}
apos += ( long ) *u;
return nbyte;
}
return read(fileds, buf, nbyte);
}
/*
* Write data to an archive file
*/
aspiwrite(fileds, buf, nbyte)
int fileds;
char *buf;
int nbyte;
{
int i;
unsigned int *u;
if ( fileds == aspifile ) {
if ( end_of_medium ) {
/*
* This only happens when an end_of_medium condition was detected
* at the previous aspiwrite() call but all bytes were written to
* the tape anyway. In this case we don't make anymore attempts to
* write to the tape but return an ENOSPC error and set the size
* of transfered bytes to 0
*/
errno = ENOSPC;
return 0;
}
u = ( unsigned int * ) &nbyte; /* Hack , i know */
if ( nbyte % ( int ) recsize ) {
( void ) fprintf(stderr,
"aspiwrite: Illegal blocklen for tape: %u\n", nbyte);
( void ) aspiclose(fileds);
exit(EX_SYSTEM);
}
i = SCSIWrite(TARGET, buf, ( long ) *u, logrec, 1, rsense);
if ( i == E$EndOfMedium ) {
unsigned int bytes_read;
end_of_medium = 1;
if ( (rsense[0] & 0x80) && (rsense[6] || rsense[5]) ) {
/* return the real number of bytes that were written to the tape */
errno = ENOSPC;
bytes_read = *u - ((rsense[6]+(rsense[5]<<8))<<logrec);
apos += ( long ) bytes_read;
return ( int ) bytes_read;
} else i = 0; /* do not return an error if all bytes were written */
}
if ( i ) { /* any other error we can't recover */
( void ) fprintf(stderr,"aspiwrite: errno: %d\n", i);
( void ) aspiclose(fileds);
exit(EX_SYSTEM);
}
apos += ( long ) *u;
return nbyte;
}
return write(fileds, buf, nbyte);
}
/*
* close an archive file
*/
aspiclose(fileds)
int fileds;
{
int i;
if ( fileds == aspifile ) {
/* first, write a filemark ! */
if ( write_file_mark_on_close && (!end_of_medium) )
if ( (i=SCSIWriteFilemarks(TARGET, 1l, 0, 0, 0)) )
( void ) fprintf(stderr,"aspiclose: Error writing filemark\n");
/* then rewind the tape if we have to */
if ( ! no_rewind ) {
if ( (i=SCSIRewind(TARGET, 0, 0)) )
( void ) fprintf(stderr,"aspiclose: Error rewinding the tape\n");
} else if ( ! write_file_mark_on_close ) {
/*
* This means we've been reading an archive on a "/dev/nrct" tape.
* In this case we have seek over the filemark at the end of the
* archive.
*/
if ( (i=SCSISpace(TARGET, 1, 1l, 0)) )
( void ) fprintf(stderr,"aspiclose: Error seeking filemark\n");
}
apos = 0l;
}
return close(fileds);
}
/*
* Seek on the archive file
*/
long aspilseek(fileds, offset, w